﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using XMLGener.Interfaces;

namespace XMLGener.Data
{
    /// <summary>
    /// This class is used as base element for XMLGenerElement and XMLGenerElements
    /// for setting ranges (min/max count/depth ... )
    /// </summary>
    public class XMLGenerRangeElement : XMLGenerNode, XMLGenerCalculatingInterface
    {
        /// <summary>
        /// Constructor
        /// </summary>
        protected XMLGenerRangeElement()
            : base()
        {
        }


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="name"></param>
        /// <param name="parent"></param>
        public XMLGenerRangeElement(String name, XMLGenerNode parent)
            : base(name, parent)
        {
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="xmlElem"></param>
        public XMLGenerRangeElement(XMLGenerNode parent, XmlElement xmlElem)
            : base(parent,xmlElem)
        {
        }


        //---------------------------
        // attributes from xml
        //---------------------------

        private int _minCount = int.MinValue;
        /// <summary>
        /// 
        /// </summary>
        public virtual int minCount
        {
            get {  
                if (_minCount==int.MinValue)
                    _minCount = getIntXMLParam("mincount",0,int.MaxValue);
                return _minCount;
            }
            set {
                _minCount = value;
                setIntXMLParam("mincount", value); 
                if (value > this.maxCount) this.maxCount = value;
            }
        }

        private int _maxCount = int.MinValue;
        
        /// <summary>
        /// 
        /// </summary>
        public virtual int maxCount
        {
            get { 
                if (_maxCount == int.MinValue)
                    _maxCount=getIntXMLParam("maxcount",0,int.MaxValue);
                return _maxCount;
            }
            set {
                _maxCount = value;
                setIntXMLParam("maxcount", value);
                if (value < minCount) minCount = value;
            }
        }

        //private int _useDepth = -1;

        /// <summary>
        /// Indicator for using depth boundaries.
        /// </summary>
        public virtual bool useDepth
        {
            get { 
                return getIntXMLParam("usedepth", 0, int.MaxValue) != 0; 
            }
            set { 
                setIntXMLParam("usedepth", (value) ? 1 : 0); 
            }
        }

        /// <summary>
        /// Minimal depth
        /// </summary>
        public virtual int minDepth
        {
            get { return getIntXMLParam("mindepth", 0, 100); }
            set
            {
                setIntXMLParam("mindepth", value);
                if (value > maxDepth) maxDepth = value;
            }
        }

        /// <summary>
        /// Maximal depth
        /// </summary>
        public virtual int maxDepth
        {
            get { return getIntXMLParam("maxdepth",0,100); }
            set {
                setIntXMLParam("maxdepth", value);
                if (value < minDepth) minDepth = value;
            }
        }

        private int _useFrequency = -1;
        /// <summary>
        /// Indicator for using frequency or count (if useFrequency = false)
        /// </summary>
        public virtual bool useFrequency
        {
            get {
                if(_useFrequency == -1)
                    _useFrequency = getIntXMLParam("usefrequency", 0, 1) ;
                return _useFrequency != 0;
            }
            set { 
                _useFrequency = (value) ? 1 : 0;
                setIntXMLParam("usefrequency", _useFrequency); 
            }
        }

        private decimal _minFrequency = -1;
        /// <summary>
        /// Use frequency for setting count of this element
        /// </summary>
        public virtual decimal minFrequency
        {
            get { 
                if (_minFrequency==-1)
                    _minFrequency =getDecimalXMLParam("minfrequency", 0, 100);
                return _minFrequency;
            }
            set {
                _minFrequency = value;
                setDecimalXMLParam("minfrequency", value); 
                if (maxFrequency < value) maxFrequency = value;
            }
        }
        private decimal _maxFrequency = -1;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxFrequency
        {
            get { 
                if (_maxFrequency==-1)
                    _maxFrequency=getDecimalXMLParam("maxfrequency", 0, 100);
                return _maxFrequency;
            }
            set {
                _maxFrequency = value;
                setDecimalXMLParam("maxfrequency", value);
                if (minFrequency > value) minFrequency = value;
            }
        }

        private int _useFanout = -1;
        /// <summary>
        /// Indicator for using fanout
        /// </summary>
        public virtual bool useFanout
        {
            get { 
                if (_useFanout == -1)
                    _useFanout= getIntXMLParam("usefanout", 0, 1);
                return _useFanout != 0;
            }
            set {
                _useFanout=(value) ? 1 : 0;
                setIntXMLParam("usefanout", _useFanout); 
            }
        }

        private decimal _minFanout = -1; 
        /// <summary>
        /// Fanout value = count of child elements
        /// </summary>
        public virtual decimal minFanout
        {
            get { 
                if (_minFanout == -1)
                   _minFanout=getDecimalXMLParam("minfanout", 0, MAX_ELEMENTS_COUNT);
                return _minFanout;
            }
            set {
                _minFanout = value;
                setDecimalXMLParam("minfanout", value);
                if (value > maxFanout) maxFanout = value;
            }
        }

        private decimal _maxFanout = -1;
        /// <summary>
        /// Fanout value = count of child elements
        /// </summary>
        public virtual decimal maxFanout
        {
            get {
                if (_maxFanout == -1)
                    _maxFanout=getDecimalXMLParam("maxfanout", 0, MAX_ELEMENTS_COUNT);
                return _maxFanout;
            }
            set {
                _maxFanout = value;
                setDecimalXMLParam("maxfanout", value);
                if (value < minFanout) minFanout = value;
            }
        }

        //------------------------------------------
        // calculation
        //------------------------------------------

        private decimal _sumMinChFreq = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChFreq
        {
            get { return _sumMinChFreq; }
            set { _sumMinChFreq = value; }
        }

        private decimal _sumMaxChFreq = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChFreq
        {
            get { return _sumMaxChFreq; }
            set { _sumMaxChFreq = value; }
        }
        
        private decimal _sumMinChCount = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChCount
        {
            get { return _sumMinChCount; }
            set { _sumMinChCount = value; }
        }
        
        private decimal _sumMaxChCount = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChCount
        {
            get { return _sumMaxChCount; }
            set { _sumMaxChCount = value; }
        }
        
        private bool _chUsesCount = false;
        /// <summary>
        /// 
        /// </summary>
        public virtual bool chUsesCount
        {
            get { return _chUsesCount; }
            set { _chUsesCount = value; }
        }        

        private bool _chUsesFreq = false;
        /// <summary>
        /// 
        /// </summary>
        public virtual bool chUsesFreq
        {
            get { return _chUsesFreq; }
            set { _chUsesFreq = value; }
        }        
        
        private decimal _sumMaxChMixCount = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChMixCount
        {
            get { return _sumMaxChMixCount; }
            set { _sumMaxChMixCount = value; }
        }        

        private decimal _sumMinChMixCount = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChMixCount
        {
            get { return _sumMinChMixCount; }
            set { _sumMinChMixCount = value; }
        }

        private List<XMLGenerCalculatingInterface> _childList = null;
        /// <summary>
        /// 
        /// </summary>
        public virtual List<XMLGenerCalculatingInterface> childList
        {
            get {
                if (_childList == null)
                {
                    _childList = new List<XMLGenerCalculatingInterface>();
                    foreach (XMLGenerCalculatingInterface n in this.childNodes)
                        if (n != null) _childList.Add(n);
                }
                return this._childList; 
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal _minCurrentCount = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal minCurrentCount
        {
            get { return _minCurrentCount; }
            set { _minCurrentCount = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal _maxCurrentReserve = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxCurrentReserve
        {
            get { return _maxCurrentReserve; }
            set { _maxCurrentReserve = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public decimal percentualReserver = 0;
        /// <summary>
        /// 
        /// </summary>
        public decimal _minTotalElemens = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal minTotalElemens
        {
            get { return _minTotalElemens; }
            set { _minTotalElemens = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal _maxTotalElemens = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxTotalElemens
        {
            get { return _maxTotalElemens; }
            set { _maxTotalElemens = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool childsTotalCalculated = false;

       
        /// <summary>
        /// 
        /// </summary>
        public decimal _countForMinTotal = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal countForMinTotal
        {
            get { return _countForMinTotal; }
            set { _countForMinTotal = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal _countForMaxTotal = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal countForMaxTotal
        {
            get { return _countForMaxTotal; }
            set { _countForMaxTotal = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public class MinTotalComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.minTotalElemens.CompareTo(x.minTotalElemens);
            }

            #endregion
        }
        /// <summary>
        /// 
        /// </summary>
        public class MaxTotalComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.maxTotalElemens.CompareTo(x.maxTotalElemens);
            }

            #endregion
        }

        /// <summary>
        /// 
        /// </summary>
        public class MaxFreqComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.maxFrequency.CompareTo(x.maxFrequency);
            }

            #endregion
        }


    }
}
